<template>
  <div>
    <Row>
      <template v-if="!isImage && getDataSchemas.length > 0">
        <Tabs>
          <template v-for="item in getDataSchemas" :key="item.Name">
            <TabPane :tab="item.Name">
              <BasicTable
                @register="registerTable"
                :columns="item.Columns"
                :dataSource="item.Data"
                @resize-column="handleResizeColumn"
              />
            </TabPane>
          </template>
        </Tabs>
      </template>
      <template v-if="isImage">
        <Image
          height="300px"
          :src="getFileBase64"
          fallback=""
        />
      </template>
    </Row>
    <Row>
      <template v-if="getDataSchemas.length > 0">
        <a-button type="link" @click="handleDataDownload"> {{ DATA_FILE_NAME }} </a-button>
      </template>
      <template v-if="hasFile">
        <a-button type="link" @click="handleFileDownload"> {{ getValue.FileName }} </a-button>
      </template>
    </Row>
  </div>
</template>

<script lang="ts" setup>
  import { computed, h } from 'vue';
  import { Row, Tabs, Image } from 'ant-design-vue';
  import { BasicTable, BasicColumn, useTable } from '@/components/Table';
  import Icon from '@/components/Icon/Icon.vue';
  import { propTypes } from '@/utils/propTypes';
  import { formatToDate } from '@/utils/dateUtil';
  import { isBoolean, isString } from '@/utils/is';
  import { downloadByBase64 } from '@/utils/file/download';

  import * as xlsx from 'xlsx';
  import type { JSON2SheetOpts, WorkBook } from 'xlsx';

  /** 数据架构 */
  export interface DataSchema {
    /** 名称 */
    Name: string;
    /** 列集合 */
    Columns: BasicColumn[];
    /** 数据 */
    Data: any[];
  }

  defineOptions({ name: 'QueryMessagePayloadPreview' });
  const props = defineProps({
    value: propTypes.any.def(null),
  });

  const { utils, writeFile } = xlsx;

  const getValue = computed(() => {
    const { value } = props;
    if (value) {
      if (isString(value)) {
        return JSON.parse(value);
      }
      return value;
    }
    return {};
  });
  const hasFile = computed(
    () =>
      getValue.value?.FileName !== undefined &&
      getValue.value?.FileName !== null &&
      getValue.value?.FileName !== '',
  );
  const isImage = computed(
    () => getValue.value?.FileBase64Header?.toLowerCase()?.indexOf('data:image/') != -1 || false,
  );
  const getFileBase64 = computed(
    () => `${getValue.value?.FileBase64Header}${getValue.value?.FileBase64String}`,
  );

  const getDataSchemas = computed(() => {
    const dataSchemas: DataSchema[] = [];
    if (getValue.value?.DataSchema?.Tables?.length <= 0) {
      return dataSchemas;
    }
    getValue.value?.DataSchema?.Tables.forEach((item: any) => {
      const cols = item.Columns.map((col: any) => {
        let width = 100;
        let format: any = undefined;
        let customRender: any = undefined;
        let dataType = 'string';
        const dataTypeString = col?.DataType?.toLowerCase() || '';
        if ((dataTypeString.indexOf('datetime') != -1 || false) === true) {
          dataType = 'datetime';
          width = 150;
          format = (text: string, _record: any, _index: number) =>
            formatToDate(text, 'YYYY-MM-DD HH:mm:ss');
        } else if ((dataTypeString.indexOf('boolean') != -1 || false) === true) {
          dataType = 'boolean';
          width = 80;
          customRender = ({ text }) => {
            if (isBoolean(text)) {
              return h(Icon, {
                icon: text ? 'ant-design:check-outlined' : 'ant-design:close-outlined',
                color: text ? '#48a5ea' : '#e25e37',
              });
            }
          };
        }
        // console.log(col);
        return {
          title: col.Display,
          dataIndex: col.Name,
          dataType: dataType,
          width,
          format,
          customRender,
          resizable: true,
        };
      });

      const data = JSON.parse(
        JSON.stringify(getValue.value?.Data[item.Name], function (key, value) {
          const dataType = cols.find((item: any) => item.dataIndex === key)?.dataType;
          if (dataType === 'datetime') {
            return formatToDate(this[key], 'YYYY-MM-DD HH:mm:ss');
          }
          return value;
        }),
      );
      dataSchemas.push({
        Name: item.Name,
        Columns: cols,
        Data: data,
      });
    });
    return dataSchemas;
  });

  const [registerTable] = useTable({
    title: undefined,
    size: 'small',
    showTableSetting: false,
    canResize: false,
    pagination: false,
    scroll: { y: 200 },
  });

  const DATA_FILE_NAME = 'Data.xlsx';
  /** 处理数据下载 */
  function handleDataDownload() {
    if (getDataSchemas.value.length > 0) {
      const workbook: WorkBook = { SheetNames: [], Sheets: {} };
      getDataSchemas.value.forEach((item) => {
        //设置列标题
        const columns = item.Columns;
        let header = {};
        columns.forEach((col: any) => {
          header[col.dataIndex] = col.title;
        });
        //处理列数据
        const arrData = [...item.Data];
        // console.log(arrData);
        arrData.unshift(header);
        //处理Excel
        const json2sheetOpts: JSON2SheetOpts = { skipHeader: true };
        const worksheet = utils.json_to_sheet(arrData, json2sheetOpts);
        setExcelColumnWidth(arrData, worksheet);

        /* add worksheet to workbook */
        const sheetName = item.Name;
        workbook.SheetNames = [...workbook.SheetNames, sheetName];
        workbook.Sheets = { ...workbook.Sheets, [sheetName]: worksheet };
      });
      /* output format determined by filename */
      writeFile(workbook, DATA_FILE_NAME, { bookType: 'xlsx' });
      // console.log(getValue.value.Data);
    }
  }
  /**
   * @param data source data
   * @param worksheet worksheet object
   * @param min min width
   */
  function setExcelColumnWidth(data: any, worksheet: any, min = 3) {
    const obj = {};
    worksheet['!cols'] = [];
    data.forEach((item: any) => {
      Object.keys(item).forEach((key) => {
        const cur = item[key];
        const length = cur?.length ?? min;
        obj[key] = Math.max(length, obj[key] ?? min);
      });
    });
    Object.keys(obj).forEach((key) => {
      worksheet['!cols'].push({
        wch: obj[key],
      });
    });
  }

  /** 处理文件下载 */
  async function handleFileDownload() {
    if (getValue.value?.FileName && getFileBase64.value) {
      downloadByBase64(getFileBase64.value, getValue.value.FileName);
    }
  }

  const handleResizeColumn = (w: any, col: any) => {
    col.width = w;
  };
</script>
